package com.example.demo.widget.chart.semicircle

import android.content.Context
import android.graphics.*
import android.os.Build
import android.support.annotation.ColorInt
import android.support.annotation.RequiresApi
import android.util.AttributeSet
import android.view.View
import com.example.demo.R
import com.example.demo.widget.chart.ChartData
import com.example.demo.widget.chart.pie.PieChartHelper
import com.example.demo.widget.chart.utils.ChartDataUtils
import com.example.demo.widget.chart.utils.DrawTextUtils
import com.example.demo.widget.chart.utils.MathUtils
import kotlinx.android.synthetic.main.activity_main.view.*
import kotlin.math.ceil
import kotlin.math.roundToInt

/**
 * 半圆形统计图
 *
 *
app:semicircle_total_text_size 总数文字大小
app:semicircle_total_text_color 总数文字颜色
app:semicircle_flag_text_size 颜色标识文字大小
app:semicircle_flag_text_color 颜色标识文字颜色
app:semicircle_flag_circle_radius 颜色标识圆形半径
app:semicircle_flag_circle_text_padding 颜色标识文字和圆形之间的距离
app:semicircle_flag_padding 两个标识之间的距离
app:semicircle_chart_flag_padding 标识和图形之间的距离
app:semicircle_chart_size 图形线条宽度
app:semicircle_chart_padding_size 两个间隔之间的大小
app:semicircle_chart_to_left 到左边的距离
app:semicircle_chart_to_right 到右边的距离
app:semicircle_chart_to_top 到上边的距离
app:semicircle_chart_padding_color 间距颜色
 *
 * @author wangheng
 */
class SemicircleView : View {

    companion object {
        private const val START_ANGLE = -180f
        private const val TOTAL_ANGLE = 180f

    }

    constructor(context: Context?) : super(context){
        initView(context,null)
    }
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs){
        initView(context,attrs)
    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ){
        initView(context,attrs)
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes){
        initView(context,attrs)
    }
    private var mData: ChartData? = null
    private var mRadius: Float = 0f

    private var mInnerRadius = 0f
    private var mOuterRadius = 0f

    private var mCenterX: Float = 0f
    private var mCenterY: Float = 0f
    private var mChartRectF = RectF()

    // 图形线条宽度
    private var mChartSize = 10f
    // 图形宽度占可用宽度的比例
    private var mChartWidthRatio = 1.0f

    // comment说明文字相关属性
    private var mCommentTopTextSize = 12f
    private var mCommentTopTextColor = Color.BLACK
    private var mCommentTopTextPadding = 5f
    private var mCommentTopTextBold = false
    // 注释线宽度
    private var mCommentLineSize = 1f

    // 分割线大小
    private var mChartPaddingSize = 1f
    // 分割线颜色
    private var mChartPaddingColor = Color.WHITE

    private var mChartPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mChartPaddingPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mCommentTopTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mCommentLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)

    private fun initView(context: Context?, attrs: AttributeSet?) {
        if(context != null){
            val ta = context.obtainStyledAttributes(attrs, R.styleable.SemicircleView)
            // app:semicircle_chart_size 图形线条宽度
            mChartSize = ta.getDimension(R.styleable.SemicircleView_semicircle_chart_size,mChartSize)
            // app:semicircle_chart_padding_size 两个间隔之间的大小
            mChartPaddingSize = ta.getDimension(R.styleable.SemicircleView_semicircle_chart_padding_size,mChartPaddingSize)
            // app:semicircle_chart_padding_color 间隔颜色
            mChartPaddingColor = ta.getColor(R.styleable.SemicircleView_semicircle_chart_padding_color,mChartPaddingColor)
            // 图形宽度占可用宽度的比例
            mChartWidthRatio = ta.getFloat(R.styleable.SemicircleView_semicircle_chart_width_ratio,mChartWidthRatio)

            /**
             *
            <attr title="semicircle_comment_top_text_size" format="dimension"/>
            <attr title="semicircle_comment_top_text_color" format="color"/>
            <attr title="semicircle_comment_top_text_padding" format="dimension"/>
            <attr title="semicircle_comment_top_text_bold" format="boolean"/>
             */
            mCommentTopTextSize = ta.getDimension(R.styleable.SemicircleView_semicircle_comment_top_text_size,mCommentTopTextSize)
            mCommentTopTextColor = ta.getColor(R.styleable.SemicircleView_semicircle_comment_top_text_color,mCommentTopTextColor)
            mCommentTopTextPadding = ta.getDimension(R.styleable.SemicircleView_semicircle_comment_top_text_padding,mCommentTopTextPadding)
            mCommentTopTextBold = ta.getBoolean(R.styleable.SemicircleView_semicircle_comment_top_text_bold,mCommentTopTextBold)
            // 注释线
            mCommentLineSize = ta.getDimension(R.styleable.SemicircleView_semicircle_comment_line_size,mCommentLineSize)
            ta.recycle()
        }

        // 扇形Paint
        mChartPaint.style = Paint.Style.STROKE
        mChartPaint.strokeWidth = mChartSize

        // 分割线
        initLinePaint(mChartPaddingPaint,mChartPaddingSize,mChartPaddingColor)
        // 注释线
        initLinePaint(mCommentLinePaint,mCommentLineSize,Color.BLACK)

        // 顶部文字
        initTextPaint(mCommentTopTextPaint,mCommentTopTextSize,mCommentTopTextColor)
        mCommentTopTextPaint.isFakeBoldText = mCommentTopTextBold

        // 给帮助类设置信息
        mChartCommentHelper.mCommentLineSize = mCommentLineSize
        mChartCommentHelper.mChartSize = mChartSize
        mChartCommentHelper.mCommentTopTextPadding = mCommentTopTextPadding
        mChartCommentHelper.mCommentTopTextPaint = mCommentTopTextPaint
    }

    private fun initLinePaint(paint: Paint,size: Float,@ColorInt color: Int){
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = size
        paint.color = color
    }

    private fun initTextPaint(paint: Paint,textSize: Float,@ColorInt color: Int){
        paint.textSize = textSize
        paint.color = color
    }

    private var mChartCommentHelper = SemicircleChartHelper()
    private var mDrawRect = RectF()

    private fun receiveDrawInfo(pWidth: Float,pHeight: Float) {
        val halfSize = mChartSize / 2f
        // 减去两个绘制的宽度的一半，应该写成上面的语句，优化成下面的语句
        mCenterX = (pWidth - paddingLeft - paddingRight) / 2f + paddingLeft
        mCenterY = pHeight

        val left = mCenterX - mRadius        // 减去宽度的一般的原因是在绘制边框时，半绘制在给定的坐标外面，一半绘制在坐标的里面
        val top = mCenterY - mRadius
        val right = mCenterX + mRadius
        val bottom = mCenterY + mRadius

        mChartRectF.set(left,top,right,bottom)
        mInnerRadius = mRadius - halfSize
        mOuterRadius = mRadius + halfSize

        // 给帮助类设置信息
        mChartCommentHelper.mRadius = mRadius
        mChartCommentHelper.mCenterX = mCenterX
        mChartCommentHelper.mCenterY = mCenterY

        mChartCommentHelper.mDrawRect = mDrawRect

        mChartCommentHelper.calculateCommentInfo()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        if(widthMode == MeasureSpec.EXACTLY && widthSize > 0){
            val heightMode = MeasureSpec.EXACTLY

            val spaceWidth = (widthSize - paddingLeft - paddingRight) * (1 - mChartWidthRatio)
            mRadius = ((widthSize - paddingLeft - paddingRight) * mChartWidthRatio - mChartSize) / 2f

            mChartCommentHelper.setLeftRightSpace(spaceWidth / 2f)
            val heightDelta = mChartCommentHelper.getTopHeight(spaceWidth / 2f)

            val heightSize = ceil(paddingTop + paddingBottom + mChartSize / 2.0f + mRadius + heightDelta).roundToInt()
            val hSpec = MeasureSpec.makeMeasureSpec(heightSize,heightMode)
            super.onMeasure(widthMeasureSpec, hSpec)

            mDrawRect.left = paddingLeft.toFloat()
            mDrawRect.right = (widthSize - paddingRight).toFloat()
            mDrawRect.top = paddingTop.toFloat()
            mDrawRect.bottom = (heightSize - paddingBottom).toFloat()


            receiveDrawInfo(widthSize.toFloat(),heightSize.toFloat())
        }else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        }
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if(canvas != null) {
            drawItemList(canvas)
            drawCommentList(canvas)
        }
    }

    private fun drawCommentList(canvas: Canvas) {
        val list = mData?.itemList ?: return
        val size = list.size
        if(size == 0){
            return
        }
        list.forEach {
            if(it.onlyDrawColor){
                return@forEach
            }
            // 绘制上面的文字
            DrawTextUtils.drawTextOnRectCenter(canvas,mCommentTopTextPaint,it.title,it.titleRect)
            // 绘制第一条线段
            mCommentLinePaint.color = it.color
            val firstPoint = it.firstPoint
            val secondPoint = it.secondPoint
            val thirdPoint = it.thirdPoint

//            path.reset()
//            path.moveTo(firstPoint.x,firstPoint.y)
//            val controlX = firstPoint.x + (secondPoint.x - firstPoint.x) / 2f
//            val controlY = min(firstPoint.y,secondPoint.y) - mCommentTopTextSize - mCommentTopTextPadding * 2
//            path.quadTo(controlX,controlY,secondPoint.x,secondPoint.y)
//            canvas.drawPath(path,mCommentLinePaint)
            canvas.drawLine(firstPoint.x,firstPoint.y,secondPoint.x,secondPoint.y,mCommentLinePaint)
            // 绘制第二条线段
            canvas.drawLine(secondPoint.x,secondPoint.y,thirdPoint.x,thirdPoint.y,mCommentLinePaint)
        }
    }

    private val mPointPairList = ArrayList<PointPair>()

    // 绘制列表
    private fun drawItemList(canvas: Canvas) {
        val totalAngle = 180f
        val list = mData?.itemList ?: return

        val listSize = list.size
        if(list.size == 0){
            return
        }

        val needDrawPadding = mChartPaddingSize > 0 && listSize > 1
        if(needDrawPadding){
            mPointPairList.clear()
        }
        for(index in 0 until listSize){
            val item = list[index]
            mChartPaint.color = item.color
            canvas.drawArc(mChartRectF,item.startAngle,item.swipeAngle,false,mChartPaint)
            if(needDrawPadding && index != listSize - 1){
                val angle = item.startAngle + item.swipeAngle
                val inner = MathUtils.getPointF(
                    mCenterX,
                    mCenterY,
                    mInnerRadius,angle)
                val outer = MathUtils.getPointF(
                    mCenterX,
                    mCenterY,
                    mOuterRadius,angle)
                mPointPairList.add(PointPair(inner, outer))
            }
        }

        if(needDrawPadding && mPointPairList.isNotEmpty()){
            mPointPairList.forEach {
                canvas.drawLine(it.inner.x,it.inner.y,it.outer.x,it.outer.y,mChartPaddingPaint)
            }
        }
    }

    private class PointPair(val inner: PointF, val outer: PointF)

    fun setData(data: ChartData?) {
        mData = data
        // 给帮助类设置数
        mChartCommentHelper.mList = mData?.itemList
        // 收集每一个item开始和扫过的角度的信息
        ChartDataUtils.receiveItemAngleInfo(mData, START_ANGLE, TOTAL_ANGLE)
        // 重新布局
        requestLayout()
    }


}